package com.sun.gis.radar;

import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.*;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import java.awt.geom.Point2D;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class CircleToGeoJSON1 {
    public static void main(String[] args) {
        try {
            Coordinate centerCoord = new Coordinate(118.796877, 32.060255); // 南京的经纬度
            double maxRadius = 100000; // 最大半径100公里
            int numSectors = 360; // 36个扇形
            int radiusStep = 100; // 每100米一个扇形层

            // 创建FeatureCollection
            SimpleFeatureType featureType = createFeatureType();
            DefaultFeatureCollection collection = new DefaultFeatureCollection("internal", featureType);

            // 添加扇形
            GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
            SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(featureType);
            populateFeatureCollection(collection, featureBuilder, geometryFactory, centerCoord, maxRadius, numSectors, radiusStep);

            // 输出到GeoJSON
            if (collection.size() > 0) {
                File file = new File("D:\\data\\radar\\nanjing_circle_sectors360.geojson");
                try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                    FeatureJSON fjson = new FeatureJSON();
                    fjson.writeFeatureCollection(collection, writer);
                    System.out.println("GeoJSON file created: " + file.getAbsolutePath());
                }
            } else {
                System.out.println("No features to write.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SimpleFeatureType createFeatureType() {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName("Sector");
        builder.setCRS(DefaultGeographicCRS.WGS84); // WGS 84 coordinate reference system
        builder.add("geometry", Polygon.class);
        builder.add("id", Integer.class);
        return builder.buildFeatureType();
    }

    private static void populateFeatureCollection(DefaultFeatureCollection collection, SimpleFeatureBuilder featureBuilder, GeometryFactory geometryFactory, Coordinate center, double maxRadius, int numSectors, int radiusStep) {
        GeodeticCalculator calculator = new GeodeticCalculator();

        for (int i = 0; i < numSectors; i++) {
            double startAngle = i * (360.0 / numSectors);
            double endAngle = (i + 1) * (360.0 / numSectors);

            for (double radius = radiusStep; radius <= maxRadius; radius += radiusStep) {
                Polygon sector = createSector(geometryFactory, calculator, center, radius - radiusStep, radius, startAngle, endAngle);
                if (sector != null && !sector.isEmpty() && sector.isValid()) {
                    featureBuilder.add(sector);
                    featureBuilder.add(i * 1000 + (int) radius);
                    SimpleFeature feature = featureBuilder.buildFeature(null);
                    collection.add(feature);
                } else {
                    System.out.println("Invalid geometry for sector " + i + " at radius " + radius);
                }
            }
        }
    }

    private static Polygon createSector(GeometryFactory geometryFactory, GeodeticCalculator calculator, Coordinate center, double innerRadius, double outerRadius, double startAngle, double endAngle) {
        CoordinateList coordinates = new CoordinateList();
        addArc(coordinates, calculator, center, innerRadius, startAngle, endAngle, false);
        addArc(coordinates, calculator, center, outerRadius, startAngle, endAngle, true);
        coordinates.add(coordinates.get(0)); // close the polygon

        LinearRing shell = geometryFactory.createLinearRing(coordinates.toCoordinateArray());
        return geometryFactory.createPolygon(shell, null);
    }

    private static void addArc(CoordinateList coordinates, GeodeticCalculator calculator, Coordinate center, double radius, double startAngle, double endAngle, boolean reverse) {
        int numPoints = 20; // More points for better accuracy
        double step = (endAngle - startAngle) / numPoints;
        for (int j = 0; j <= numPoints; j++) {
            double angle = reverse ? endAngle - j * step : startAngle + j * step;
            calculator.setStartingGeographicPoint(center.x, center.y);
            calculator.setDirection(angle, radius);
            Point2D point = calculator.getDestinationGeographicPoint();
            coordinates.add(new Coordinate(point.getX(), point.getY()));
        }
    }
}
